﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using HtmlAgilityPack;

namespace DeepMixWorkflow
{
    public class NowPlayingParser
    {
        private static readonly Regex DurationRegexExpression = new Regex(@"\((?<hours>\d{2})h:(?<minutes>\d{2})m\)");
        private readonly HtmlDocument _htmlDocument;

        public NowPlayingParser(string html)
        {
            _htmlDocument = new HtmlDocument();
            _htmlDocument.LoadHtml(html);
        }

        private string GetOnAirPlainText()
        {
            HtmlNode onAirSpan = _htmlDocument.DocumentNode.SelectSingleNode("//span[@class='playnow']");
            return onAirSpan.InnerText.Trim();
        }

        public DeepMixTrack GetNowPlayingTrack()
        {
            string plainText = GetOnAirPlainText();
            Match match = CommonHelper.TrackTitleRegex.Match(plainText);
            GroupCollection groups = match.Groups;

            return new DeepMixTrack {Title = groups["track"].Value, Artist = groups["artist"].Value};
        }

        public TimeSpan GetMoscowTime()
        {
            HtmlNodeCollection fontNodes = _htmlDocument.DocumentNode.SelectNodes("//td[@class='content']/font");
            HtmlNode moscowTimeLabel = fontNodes.Single(f => f.InnerText.Contains(@"Deep Mix Moscow Time:"));
            HtmlNode nowPlayingFont = fontNodes.SkipWhile(f => f != moscowTimeLabel).Skip(1).Take(1).Single();
            string timeText = nowPlayingFont.SelectSingleNode("./strong").InnerText;
            return ExtractStartTime(timeText);
        }

        private static TimeSpan ExtractStartTime(string timeText)
        {
            string[] strings = timeText.Split(':');

            var moscowTime = new TimeSpan(int.Parse(strings[0]),
                                          int.Parse(strings[1]), 0);
            return moscowTime;
        }

        public DeepMixTrack[] GetProgram()
        {
            HtmlNode contentTd = _htmlDocument.DocumentNode.SelectNodes("//td[@class='content']").ElementAt(2);
            DeepMixTrack firstTrack = GetFirstTrack(contentTd);
            IEnumerable<DeepMixTrack> blueProgram = GetBlueProgram(contentTd);

            return new[] {firstTrack}.Union(blueProgram).ToArray();
        }

        private static IEnumerable<DeepMixTrack> GetBlueProgram(HtmlNode contentTd)
        {
            HtmlNode[] bigBlueNodes = contentTd.SelectNodes("./font[@class='bigblue']").Skip(1).ToArray();
            HtmlNode[] blueNodes = contentTd.SelectNodes("./font[@class='blue']").ToArray();

            for (int i = 0; i < bigBlueNodes.Length; i++)
            {
                string timeText = bigBlueNodes[i].InnerText;
                HtmlNode blueNode = blueNodes[i];
                string trackName = blueNode.InnerText;
                string durationText = blueNode.NextSibling.InnerText;

                DeepMixTrack deepMixTrack = CommonHelper.ParseTrackName(trackName);
                deepMixTrack.StartTime = ExtractStartTime(timeText.Split('|')[1].Trim());
                deepMixTrack.Duration = ExtractDuration(durationText);

                yield return deepMixTrack;
            }
        }

        private static DeepMixTrack GetFirstTrack(HtmlNode contentTd)
        {
            string firstProgramTimeString = contentTd.SelectSingleNode("./font[@class='biggray']").InnerText;

            string[] tts = firstProgramTimeString.Split('|')[1].Split(':');
            var startTime = new TimeSpan(
                int.Parse(tts[0].Trim()),
                int.Parse(tts[1].Trim()), 0);

            HtmlNode trackNameFont = contentTd.SelectSingleNode("./font[@class='gray']");
            string firstProgramTrackNameString = trackNameFont.InnerText;

            DeepMixTrack firstTrack = CommonHelper.ParseTrackName(firstProgramTrackNameString);
            firstTrack.StartTime = startTime;
            HtmlNode durationSibling = trackNameFont.NextSibling;
            string durationText = durationSibling.InnerText;
            firstTrack.Duration = ExtractDuration(durationText);
            return firstTrack;
        }

        private static TimeSpan ExtractDuration(string durationText)
        {
            Match match = DurationRegexExpression.Match(durationText.Trim());
            return new TimeSpan(int.Parse(match.Groups["hours"].Value), int.Parse(match.Groups["minutes"].Value),
                                0);
        }

        public string GetImagePath()
        {
            HtmlNodeCollection images = _htmlDocument.DocumentNode.SelectNodes("//img");
            foreach (HtmlNode image in images)
            {
                string source = image.Attributes["src"].Value;
                if (source.Contains(@"/img/"))
                {
                    if (source[0] == '/')
                        source = "http://deepmix.eu" + source;
                    return source;
                }
            }
            return null;
        }
    }
}